package gate // 网关消息处理器
/*
2025/10/09
实现了完整的消息处理流程
添加了节点选择算法（简单的取模负载均衡）
支持心跳包处理
提供了错误响应机制

与注册中心集成，动态发现节点服务
支持 RPC 调用到后端节点
包含连接管理和会话处理

2025/10/10
增加节点处理功能，简单负载均衡，把需要节点处理的内容分配给节点
*/

import (
	"fmt"
	"gameServer/eventbus"
	"gameServer/locate"
	"gameServer/log"
	"gameServer/packet"
	"gameServer/registry"
	"net"
)

/* //* 网关消息处理器实现，负责处理客户端连接、断开、消息接收等事件，实现消息路由分发、节点选择和RPC调用转发 */

// 网关消息处理器
type GateHandler struct {
	gate     *Gate
	registry registry.Registry // 给消息处理器也写上注册中心（目前准备和gate.go一样）
	balancer locate.Balancer   // 负载均衡器
}

// 创建网关消息处理器
func NewGateHandler(gate *Gate) *GateHandler {
	return &GateHandler{
		gate: gate,
	}
}

// 设置注册中心
func (h *GateHandler) SetRegistry(registry registry.Registry) {
	h.registry = registry
}

// 设置服务定位器
func (h *GateHandler) SetBalancer(balancer locate.Balancer) {
	h.balancer = balancer
}

// 处理连接建立
func (h *GateHandler) HandleConnect(conn net.Conn) error {
	// 这里可以处理用户连接逻辑，如用户认证等
	log.Infof("Client connected from %s", conn.RemoteAddr())

	// 发布用户连接事件
	event := eventbus.NewUserEventBus(
		eventbus.EventUserConnected,
		"", //* 用户ID，可以在认证后设置
		conn.RemoteAddr().String(),
		nil,
	)
	h.gate.eventBus.Publish(event)
	return nil
}

// 处理断开连接
func (h *GateHandler) HandleDisconnect(conn net.Conn) error {
	// 这里可以处理用户断开逻辑，如清理用户状态等
	log.Infof("Client disconnected from %s", conn.RemoteAddr())
	return nil
}

// 处理消息
func (h *GateHandler) HandleMessage(conn net.Conn, pkt *packet.Packet) error {
	// 根据路由ID将消息转发到相应的节点服务
	// 这里需要实现路由分发逻辑
	// 目前先简单回声回复
	// 这里为了测试效果，让客户端打印内容，服务端不参与，就发过来什么，发回去什么，都让客户端自己打印
	// 这样也就实现了一个终端多个服务，打印还不冲突（客户端每次都有睡眠等待）
	// Pack函数是单独的，处理这个结构体中的内容（类中static行为）（这里直接用pkt.Seq作为回复，方便验证

	if pkt.Header == packet.FlagHeartbeat {
		// 心跳包，直接回复
		_, err := conn.Write(packet.PackHeartbeat())
		return err
	}
	// 数据包，根据路由ID转发到相应的节点
	log.Infof("Received message: route=%d, seq=%d, size=%d", pkt.Route, pkt.Seq, len(pkt.Body))

	// 根据路由选择节点（简单示例）（对目标节点发送消息，先获取）(负载均衡)
	nodeID, err := h.selectNode(uint32(pkt.Route))
	if err != nil {
		log.Errorf("Failed to select node: %v", err)
		// 返回错误相应
		return h.sendErrorResponse(conn, uint32(pkt.Route), pkt.Seq, "No available node")
	}
	// 转发到节点处理
	response, err := h.gate.forwardToNode(nodeID, uint32(pkt.Route), pkt.Body)
	if err != nil {
		log.Errorf("Failed to forward to node %s: %v", nodeID, err)
		return h.sendErrorResponse(conn, uint32(pkt.Route), pkt.Seq, "Node processing failed")
	}
	// 发送相应到客户端
	_, err = conn.Write(packet.Pack(pkt.Route, pkt.Seq, response))

	//* 发布消息接收事件
	event := eventbus.NewMessageEvent(
		eventbus.EventMessageReceived,
		conn.RemoteAddr().String(),
		uint32(pkt.Route),
		pkt.Body,
	)
	h.gate.eventBus.Publish(event)

	return err
}

// 选择处理节点 优先选择健康节点
func (h *GateHandler) selectNode(route uint32) (string, error) {
	// 简单的负载均衡，根据路由 可以使用定位器
	if h.balancer == nil {
		// 没有设置负载均衡器，使用简单策略
		return h.simpleNodeSelection(route)
	}
	if h.balancer == nil {
		return "", fmt.Errorf("balancer not set")
	}
	// 使用定位器（负载均衡）选择节点（优先选择健康节点）（负载均衡使用了对应的Select）
	node, err := h.balancer.Select("node", route)
	if err != nil {
		if err == locate.ErrNoHealthyServiceAvailable {
			// 如果没有健康节点，尝试使用所有节点
			log.Warnf("No healthy service available for route %d try all nodes", route)
			return h.selectFromAllNodes(route)
		}
		return "", err
	}
	log.Infof("Selected node %s for route %d", node.ID, route)
	return node.ID, nil
	// // 检查网关处理器在注册中心是否已设置（未设置则返回错误）
	// if h.registry == nil {
	// 	return "", fmt.Errorf("registry not set")
	// }
	// // 获取所有节点服务
	// // 从注册中心查询所有"node"类型的服务（后端业务节点，如game/chat）
	// // 这里作为测试，默认这些节点都是一样的
	// services, err := h.registry.GetService("node")
	// if err != nil {
	// 	return "", err
	// }
	// // 检查是否有可用节点（无节点则返回错误）
	// if len(services) == 0 {
	// 	return "", fmt.Errorf("no available nodes")
	// }
	// // 简单负载均衡：根据路由ID取模选择节点
	// selectedIndex := int(route) % len(services)
	// selectedNode := services[selectedIndex]

	// log.Infof("Selected node %s for route %d", selectedNode.ID, route)
	// return selectedNode.ID, nil
}

// 从所有节点中选择
func (h *GateHandler) selectFromAllNodes(route uint32) (string, error) {
	if h.registry == nil {
		return "", fmt.Errorf("registry not set")
	}
	// 获取所有节点服务
	services, err := h.registry.GetService("node")
	if err != nil {
		return "", err
	}
	if len(services) == 0 {
		return "", fmt.Errorf("no services available for route %d", route)
	}
	// 简单负载均衡，根据路由ID取模选择节点
	selectedIndex := int(route) % len(services)
	selectedNode := services[selectedIndex]
	log.Infof("Selected node %s for route %d(fallback selection)", selectedNode.ID, selectedIndex)
	return selectedNode.ID, nil
}

// 发送错误响应
func (h *GateHandler) sendErrorResponse(conn net.Conn, route uint32, seq uint16, message string) error {
	errorData := []byte(fmt.Sprintf(`{"error": true, "message": "%s"}`, message))
	_, err := conn.Write(packet.Pack(uint16(route), seq, errorData))
	return err
}

// 简单节点选择策略（备用）
func (h *GateHandler) simpleNodeSelection(route uint32) (string, error) {
	log.Warnf("没有设置route:%d的选择节点策略，使用简单节点策略", route)

	if h.registry == nil {
		return "", fmt.Errorf("registry not set")
	}
	// 优先选择健康节点
	healthServices, err := h.registry.GetHealthyServices("node")
	if err != nil {
		return "", err
	}
	if len(healthServices) > 0 {
		// 有健康节点，使用健康节点
		selectedIndex := int(route) % len(healthServices)
		selectedNode := healthServices[selectedIndex]
		log.Infof("Selected node %s for route %d", selectedNode.ID, route)
		return selectedNode.ID, nil
	}
	// 获取所有节点服务（没有健康节点）
	log.Warnf("No healthy node for route %d select all nodes", route)
	services, err := h.registry.GetService("node")
	if err != nil {
		return "", err
	}
	if len(services) == 0 {
		return "", fmt.Errorf("no available nodes")
	}
	// 简单负载均衡：根据路由ID取模选择节点
	selectedIndex := int(route) % len(services)
	selectedNode := services[selectedIndex]

	log.Infof("Selected node %s for route %d (simple selection)", selectedNode.ID, route)
	return selectedNode.ID, nil
}
